package com.utils;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.ObjectError;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * json，java对象互相转换类
 *
 * @author
 * 		<ul>
 *         <li>高文相 2014 年 9月 22 日 新增
 *         <li>
 *         <ul>
 */
public class JsonUtil {

    private static String JSONUTILE_ISNULL = "(:null,|:NULL,)";
    private static String JSONUTILE_REPLACE = ":\"\",";
    private static String JSONUTILE_JSONNULL = "{}";

    private static Logger log = LoggerFactory.getLogger(JsonUtil.class);
    private static ObjectMapper objectMapper = null;
    private static JsonUtil json = null;

    /**
     * 实例化JsonUtil
     *
     * @author
     * 		<ul>
     *         <li>高文相 2014 年 9月 22 日 新增
     *         <li>
     *         <ul>
     */
    @SuppressWarnings("unused")
    private static JsonUtil instance() {
    	if (json == null) {
            json = new JsonUtil();
        }
        return json;
    }

    /**
     * 将Object对象转为JSON字符串
     *
     * @param obj
     *            JavaBean/Map/List<?> 等 例：User user， 实体User的对象 Map<String,Object> map; map对象 List<Object> list;list对象 List<Map<String,Object>> listmap;listmap对象
     * @author
     * 		<ul>
     *         <li>高文相 2014 年 9月 22 日 新增
     *         <li>
     *         <ul>
     */
    public static String ObjectToJson(Object obj) {
        if (obj == null) {
            return JSONUTILE_JSONNULL;
        }
        try {
            objectMapper = new ObjectMapper();

            SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.YYYY_MM_DD_HH_MM_SS);
            objectMapper.setDateFormat(sdf);

//			objectMapper.configure(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS, true);
//			objectMapper.configure(JsonGenerator.Feature.QUOTE_NON_NUMERIC_NUMBERS, true);
			objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
				@Override
				public void serialize(Object value, JsonGenerator jgen,
						SerializerProvider provider) throws IOException,
						JsonProcessingException {
					jgen.writeString("");
				}
            });
//            objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);

            return objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.error("Object转换json字符串错误!", e);
        }
        return JSONUTILE_JSONNULL;
    }

    /**
     * 将Object对象转为JSON字符串
     *
     * @param obj
     *            JavaBean/Map/List<?> 等 例：User user， 实体User的对象 Map<String,Object> map; map对象 List<Object> list;list对象 List<Map<String,Object>> listmap;listmap对象
     * @author
     * 		<ul>
     *         <li>高文相 2014 年 9月 22 日 新增
     *         <li>
     *         <ul>
     */
    public static String ObjectToJson2(Object obj) {
        if (obj == null) {
            return JSONUTILE_JSONNULL;
        }
        try {
            objectMapper = new ObjectMapper();
            return objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.error("Object转换json字符串错误!", e);
        }
        return JSONUTILE_JSONNULL;
    }

    /**
     * 添加元素到json字符串中
     * @param json json字符串
     * @param key 添加元素的key
     * @param value 添加元素的value
     * @return
     */
    public static String addElement2Json(String json,String key,Object value){
        Map map = JsonUtil.readJson2Map(json);
        if(map != null){
            map.put(key,value);
            try {
                json = JsonUtil.mapToJson(map);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
                return "";
            }
        }

        return json;
    }

    /**
     * 将JSON字符串转换为Object对象
     *
     * @param json
     *            需要转换的json字符串;
     * @param clas
     *            需要转换成的类型 例：List.class; User.class(实体类)
     * @author
     * 		<ul>
     *         <li>高文相 2014 年 9月 22 日 新增
     *         <li>
     *         <ul>
     */
    public static <T> T JsonToObject(String json, Class<T> clas) {
        if (json == null) {
            return null;
        }
        try {
            objectMapper = new ObjectMapper();
            SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.YYYY_MM_DD_HH_MM_SS);
            objectMapper.setDateFormat(sdf);
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            return objectMapper.readValue(json, clas);

        } catch (IOException e) {
            log.error("json转换Object错误!", e);
        }
        return null;
    }

    /**
     * 将数据集合转换为JSON字符串
     * @param list
     * @return
     */
    public static String readList2Json(List list){
        try {
            objectMapper = new ObjectMapper();
            return objectMapper.writeValueAsString(list);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            log.error("json转换Object错误!", e);
        }
        return null;
    }

    /**
     * valid验证bean类专用解析
     * @param list
     * @return
     */
    public static String readList2JsonWithError(List<ObjectError> list){
        try {
            objectMapper = new ObjectMapper();
            if(list != null && list.size() > 0){
                List<String> stringList = new ArrayList<>();
                for(ObjectError objectError:list){
                    stringList.add(objectError.getDefaultMessage());
                }
                return objectMapper.writeValueAsString(stringList);
            }
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            log.error("json转换Object错误!", e);
        }
        return null;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static List<Map<String, Object>> readJson2ListMap(String json) {
        try {
            objectMapper = new ObjectMapper();
            List objs = objectMapper.readValue(json, List.class);
            List<Map<String, Object>> maps = new ArrayList<>();
            for (Object str : objs) {
                if (str instanceof String) {
                    Map<String, Object> temp = objectMapper.readValue(str.toString(), Map.class);
                    maps.add(temp);
                }
            }
            if (!objs.isEmpty() && maps.isEmpty()) {
                return objs;
            }
            return maps;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    public static List<Map<String, Object>> readJson2ListMapNotTry(String json) throws IOException {
        objectMapper = new ObjectMapper();
        List objs = objectMapper.readValue(json, List.class);
        List<Map<String, Object>> maps = new ArrayList<>();
        for (Object str : objs) {
            if (str instanceof String) {
                Map<String, Object> temp = objectMapper.readValue(str.toString(), Map.class);
                maps.add(temp);
            }
        }
        if (!objs.isEmpty() && maps.isEmpty()) {
            return objs;
        }
        return maps;
    }

    @SuppressWarnings("unchecked")
    public static List<String> readJson2ListStr(String json) {
        try {
            objectMapper = new ObjectMapper();
            return objectMapper.readValue(json, List.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public static Map<String, Object> readJson2Map(String json) {
        try {
            objectMapper = new ObjectMapper();
            return objectMapper.readValue(json, Map.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Map<String, String> readJson2MapVString(String json) {
        try {
            objectMapper = new ObjectMapper();
            return objectMapper.readValue(json, Map.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 去掉json字符串里null或者""
     * @param json
     * @return
     */
    public static String removeJsonNull(String json) throws JsonProcessingException {
        if(json != null && !"".equals(json)){
            Map<String,Object> map = JsonUtil.readJson2Map(json);
            Map<String,Object> mapEntry = JsonUtil.readJson2Map(json);
            for(Map.Entry m: mapEntry.entrySet()){
                if(m.getValue() == null || m.getValue() == ""){
                    map.remove(m.getKey());
                }
            }
            if(map != null){
                json = JsonUtil.mapToJson(map);
            }else{
                json = "";
            }
        }
        return json;
    }

    /**
     * map 转json串
     * @param map
     * @return
     * @throws com.fasterxml.jackson.core.JsonProcessingException
     * String
     * @exception
     * @since  1.0.0
     */
    public static String mapToJson(Map<String, Object> map) throws JsonProcessingException {
        objectMapper = new ObjectMapper();
        String value = objectMapper.writeValueAsString(map);
        return value;
    }

    /**
     * 将JSON格式中的null值转换成""串
     *
     * @author
     * 		<ul>
     *         <li>高文相 2014 年 9月 22 日 新增
     *         <li>
     *         <ul>
     */
    @SuppressWarnings("unused")
    public static String convertNullToEmpty(String json) {
        return json.replaceAll(JSONUTILE_ISNULL, JSONUTILE_REPLACE);
    }

    /**
     * 设置时间格式 setDateFormate(DateUtil.ddd);
     *
     * @param dateFormt
     * @author
     * 		<ul>
     *         <li>高文相 2014 年 9月 22 日 新增
     *         <li>
     *         <ul>
     */
    public JsonUtil setDateFormate(String dateFormt) {
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormt);
        objectMapper = new ObjectMapper();
        objectMapper.setDateFormat(sdf);
        return this;
    }

}
